package com.example.scugroup8.service.impl;

import com.example.scugroup8.mapper.UserLinesMapper;
import com.example.scugroup8.mapper.UsersMapper;
import com.example.scugroup8.pojo.UserLines;
import com.example.scugroup8.pojo.Users;
import org.apache.ibatis.annotations.Param;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * (Users)表服务实现类
 *
 * @author hsx
 * @version 1.0
 * @since 2022-06-09 22:56:01
 */
@Service("usersService")
public class UsersServiceImpl {
    @Resource
    private UsersMapper usersMapper;
    @Resource
    private UserLinesMapper userLinesMapper;

    public Map<String, Object> login(String username, String password) {
        Map<String, Object> map = new HashMap<>();
        Subject subject = SecurityUtils.getSubject();                                     // shiro权限认证主体对象
        if (!subject.isAuthenticated()) {
            UsernamePasswordToken upToken = new UsernamePasswordToken(username, password);    // shiro权限认证类型
            upToken.setRememberMe(true);                                                     // 用户登录时效性
            try {
                subject.login(upToken);    // 调用realm认证用户权限  如果密码比对成功，则通过此方法
                Users users = this.getUser(username);
                String roleString = users.getRole();
                map.put("code", 200);
                map.put("msg", "登录成功");
                map.put("data", roleString);
            } catch (IncorrectCredentialsException ice) {
                map.put("code", 501);
                map.put("msg", "用户名/密码不匹配！");
            } catch (LockedAccountException lae) {
                map.put("code", 502);
                map.put("msg", "账户已被冻结！");
            } catch (UnknownAccountException uae) {
                map.put("code", 503);
                map.put("msg", "账户不存在！");
            } catch (AuthenticationException ae) {
                System.out.println(ae.getMessage());
                map.put("code", 504);
                map.put("msg", "服务繁忙，请稍候重试！");
            }
        }
        return map;
    }

    public Users getUser(@Param("username") String username) {
        return usersMapper.getUser(username);
    }

    /**
     * 根据模糊条件查询总个数
     * @param search_username 查询用户名
     * @param search_auth 查询权限
     * @return 返回查询到的总个数
     */
    public Map<String, Object> selectCount(String search_username,String search_auth) {
        Map<String, Object> map = new HashMap<>();
        // 前端端分离时，前端人员会首先判断code值是否满足200，如果不是200，则提醒用户失败
        map.put("code", 200);
        map.put("msg", "查询成功");
        map.put("list", this.usersMapper.selectCount(search_username,search_auth));
        return map;
    }

    /**
     * 查询所有数据
     *
     * @return 返回所有数据
     */
    public Map<String, Object> selectAll() {
        Map<String, Object> map = new HashMap<>();
        // 前端端分离时，前端人员会首先判断code值是否满足200，如果不是200，则提醒用户失败
        map.put("code", 200);
        map.put("msg", "查询成功");
        map.put("list", this.usersMapper.selectAll());
        return map;
    }

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    public Map<String, Object> selectById(Integer id) {
        Map<String, Object> map = new HashMap<>();
        // 前端端分离时，前端人员会首先判断code值是否满足200，如果不是200，则提醒用户失败
        map.put("code", 200);
        map.put("msg", "查询成功");
        map.put("obj", this.usersMapper.selectById(id));
        return map;
    }

    /**
     * 查询分页数据
     *
     * @param page 查询起始位置
     * @param search_username 查询用户名
     * @param search_auth 查询权限
     * @return 对象列表
     */
    public Map<String, Object> selectByPage(int page, String search_username,String search_auth) {
        // 获取当前表中的总记录
        int tableCount = this.usersMapper.selectCount(search_username, search_auth);
        // 总页码计算   (总条数 - 1) / 每页显示条数  + 1
        // (100 - 1) / 10 + 1 = 10        (101 - 1) / 10 + 1 = 11      (99 - 1) / 10 + 1 = 10
        int pageCount = (tableCount - 1) / 10 + 1;
        // 计算每页开始的下标值
        int index = (page - 1) * 10;
        Map<String, Object> map = new HashMap<>();
        map.put("code", 0);   // 前端端分离时，前端人员会首先判断code值是否满足200，如果不是200，则提醒用户失败
        map.put("msg", "查询成功");
        map.put("pageCount", pageCount);  // 查询的记录总页码
        map.put("count", tableCount);     // 当前表中的总条数
        map.put("data", this.usersMapper.selectByPage(index,search_username, search_auth));
        return map;
    }

    /**
     * 新增数据
     *
     * @param users 实例对象
     * @return 实例对象
     */
    public Map<String, Object> insert(Users users) throws ParseException {
        // UUID.randomUUID()  返回内容：asd21321-ewrewrew213213-123213zsad-123asdasd这样的形态
        Map<String, Object> map = new HashMap<>();
        if (usersMapper.getUser(users.getUsername()) == null) {
            //  注册用户
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String time = df.format(new Date());
            Date date = df.parse(time);
            users.setRegisterTime(date);
            // 将密码进行md5加密
            String md5 = md5(users.getUsername(), users.getPassword());
            users.setPassword(md5);
            this.usersMapper.insert(users);
//            将用户与设备关联
//            Users user=usersMapper.getUser(users.getUsername());
//            UserLines userLines = new UserLines();
//            userLines.setUsername(user.getUsername());
//            userLines.setUsersId(user.getId());
//            this.userLinesMapper.insert(userLines);
            map.put("code", 200);   // 前端端分离时，前端人员会首先判断code值是否满足200，如果不是200，则提醒用户失败
            map.put("msg", "新增成功");
        } else {
            map.put("code", 400);
            map.put("msg", "该用户名已注册");
        }
        return map;
    }

    /**
     * 通过ID查询单条数据
     *
     * @param users 实例对象
     * @return 实例对象
     */
    public Map<String, Object> updateById(Users users) {
        this.usersMapper.updateById(users);
        Map<String, Object> map = new HashMap<>();
        map.put("code", 200);   // 前端端分离时，前端人员会首先判断code值是否满足200，如果不是200，则提醒用户失败
        map.put("msg", "更新成功");
        return map;
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    public Map<String, Object> deleteById(String id) {
        this.usersMapper.deleteById(id);
        Map<String, Object> map = new HashMap<>();
        map.put("code", 200);   // 前端端分离时，前端人员会首先判断code值是否满足200，如果不是200，则提醒用户失败
        map.put("msg", "删除成功");
        return map;
    }

    /**
     * 注册时，进行shiro加密，返回加密后的结果，如果在加入shiro之前，存在用户密码不是此方式加密的，那么将无法登录
     * 使用用户名作为盐值
     *
     * @param username 用户名
     * @param password 密码
     * @return 返回加密加盐之后的密码格式内容
     */
    private String md5(String username, String password) {
        String hashAlgorithmName = "MD5";                   // 加密方式
        ByteSource salt = ByteSource.Util.bytes(username);  // 以账号转换为字节码，再作为盐值
        int hashIterations = 11;                            // 加密11次 可以自定义次数  加密的次数过程，会影响服务性能
        return new SimpleHash(hashAlgorithmName, password, salt, hashIterations).toString();
    }


}